import json
import random

from django import http
from django.core.paginator import Paginator
from django.db import transaction
from django.shortcuts import render
from decimal import Decimal
from orders.models import OrderInfo, OrderGoods
from django.utils import timezone

# Create your views here.
from django.views.decorators.csrf import csrf_exempt
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utils.my_loginview import LoginRequiredView
from meiduo_mall.utils.response_code import RET
from users.models import Address


class OrderSettlement(LoginRequiredView):

    def get(self, request):
        addresses = Address.objects.filter(user_id=request.user.id).all()
        # 获取购物车数据
        redis_conn = get_redis_connection('carts')
        cart_dict = redis_conn.hgetall('carts_%s' % request.user.id)
        sku_ids = redis_conn.smembers('selected_%s' % request.user.id)
        print(sku_ids)
        print(cart_dict)
        sku_list = []
        total_count = 0
        total_amount = Decimal(0.0)
        for sku_id in sku_ids:
            sku = SKU.objects.get(id=sku_id)
            sku_dict = {
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'amount': str(int(cart_dict[sku_id]) * sku.price),
                'count': int(cart_dict[sku_id]),
                'default_image_url': sku.default_image_url.url,
            }
            sku_list.append(sku_dict)
            total_count += int(cart_dict[sku_id])
            total_amount += int(cart_dict[sku_id]) * sku.price

        # 运费和实付款
        freight = Decimal(10)
        payment_amount = total_amount + freight
        context = {
            'addresses': addresses,
            'total_amount': total_amount,
            'total_count': total_count,
            'sku_list': sku_list,
            'payment_amount': payment_amount,
            'default_address_id ': request.user.default_address_id,
        }
        return render(request, 'place_order.html', context=context)


class OrderCommitView(LoginRequiredView):

    @csrf_exempt
    @transaction.atomic
    def post(self, request):
        data_dict = json.loads(request.body.decode())
        address_id = data_dict.get('address_id')
        pay_method = data_dict.get('pay_method')
        print(address_id, type(address_id))
        print(pay_method, type(pay_method))
        if not all([address_id, pay_method]):
            return http.JsonResponse({'code': RET.PARAMERR, 'errmsg': '参数不全'})

        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.JsonResponse({'code': RET.DBERR, 'errmsg': '收货地址不存在'})

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': '支付方式有误'})

        # 判断订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']

        # # 订单信息入库
        # # 生成订单编号 时间戳 + 随机字符串9位 + 用户id
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + '%09d' % random.randint(0, 999999999) + str(request.user.id)
        # order_info = OrderInfo.objects.create(
        #     order_id=order_id,
        #     user=request.user,
        #     address=address,
        #     total_count=0,
        #     total_amount=Decimal(0.0),
        #     freight=0,
        #     pay_method=pay_method,
        #     status=status,
        # )
        #
        # return
        # TODO 设置保存点
        sid = transaction.savepoint()

        order_info = OrderInfo.objects.create(
            order_id=order_id,
            user=request.user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10),
            pay_method=pay_method,
            status=status
        )

        # 4,订单商品入库
        redis_conn = get_redis_connection("carts")
        cart_dict = redis_conn.hgetall("carts_%s" % request.user.id)
        print(cart_dict)
        sku_ids = redis_conn.smembers("selected_%s" % request.user.id)
        print(sku_ids)
        if not all([cart_dict, sku_ids]):
            transaction.savepoint_rollback(sid)
            return http.JsonResponse({'code': RET.PARAMERR, 'errmsg': '您还未添加商品'})
        for sku_id in sku_ids:
            while True:
                # 4,1 获取sku,count
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                # 4,2 库存判断
                if count > sku.stock:
                    # TODO 回滚
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({"code": RET.DATAERR, "errmsg": "库存不足"})

                # 4,3 库存减少,销量增加

                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                # TODO 使用 乐观锁解决并发下单问题
                # 准备数据
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count
                new_sales = old_sales + count
                ret = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                print(ret)
                if ret == 0:
                    # transaction.savepoint_rollback(sid)
                    # return http.JsonResponse({'code': RET.NODATA, 'errmsg': '下单失败'})
                    continue

                # 4,4 创建订单商品对象
                OrderGoods.objects.create(
                    order=order_info,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )

                # 4,4 累加订单信息表
                order_info.total_count += count
                order_info.total_amount += (count * sku.price)
                break

        # 5,保存订单信息表
        order_info.save()
        # TODO 提交保存点(事务)
        transaction.savepoint_commit(sid)

        # 6,清除购物车中已经付过款的数据
        try:
            redis_conn.hdel("carts_%s" % request.user.id, *sku_ids)
            redis_conn.srem("selected_%s" % request.user.id, *sku_ids)
        except Exception as e:
            return http.JsonResponse({'code': RET.DBERR, 'errmsg': '购物车已清空'})

        # 7,返回响应
        return http.JsonResponse({"code": RET.OK, "order_id": order_id})


class OrderSuccessView(LoginRequiredView):

    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        context = {
            'order_id': order_id,
            'pay_method': pay_method,
            'payment_amount': payment_amount,
        }
        return render(request, 'order_success.html', context=context)


class UserOrderInfoView(LoginRequiredView):

    def get(self, request, page_num):
        # orders = OrderInfo.objects.filter(user_id=request.user.id).order_by('order_id')
        orders = request.user.orderinfo_set.order_by('order_id')
        print(page_num)
        for order in orders:
            order.pay_method = OrderInfo.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order.status = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]

        paginate = Paginator(object_list=orders, per_page=3)
        try:
            page = paginate.page(page_num)
        except Exception as e:
            page = paginate.page(len(orders) / 3)

        object_list = page.object_list  # 当前页的对象列表
        current_page = page.number  # 当前页
        total_page = paginate.num_pages  # 总页数
        context = {
            'orders': object_list,
            'current_page': current_page,
            'total_page': total_page,
        }

        return render(request, 'user_center_order.html', context=context)









